/*
 * Copyright 2021 Roberto Leinardi.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.leinardi.ohos.speeddial;

import ohos.agp.components.element.Element;
import ohos.agp.components.element.VectorElement;
import ohos.app.Context;
import ohos.utils.Parcel;
import ohos.utils.Sequenceable;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class SpeedDialActionItem implements Sequenceable {
    public static final int RESOURCE_NOT_SET = Integer.MIN_VALUE;

    @Retention(RetentionPolicy.RUNTIME)
    public @interface FabType { };
    public static final String TYPE_NORMAL = "normal";
    public static final String TYPE_FILL = "fill";

    private int mId;
    private String mLabel;
    private int mLabelRes;
    private String mContentDescription;
    private int mContentDescriptionRes;
    private int mFabImageResource;
    private Element mFabImageDrawable;
    private int mFabImageTintColor;
    private boolean mFabImageTint;
    private String mFabType;
    private int mFabBackgroundColor;
    private int mLabelColor;
    private int mLabelBackgroundColor;
    private boolean mLabelClickable;
    private int mFabSize;
    private int mTheme;

    private SpeedDialActionItem() {
    }

    private SpeedDialActionItem(Builder builder) {
        mId = builder.mId;
        mLabel = builder.mLabel;
        mLabelRes = builder.mLabelRes;
        mContentDescription = builder.mContentDescription;
        mContentDescriptionRes = builder.mContentDescriptionRes;
        mFabImageTintColor = builder.mFabImageTintColor;
        mFabImageTint = builder.mFabImageTint;
        mFabType = builder.mFabType;
        mFabImageResource = builder.mFabImageResource;
        mFabImageDrawable = builder.mFabImageDrawable;
        mFabBackgroundColor = builder.mFabBackgroundColor;
        mLabelColor = builder.mLabelColor;
        mLabelBackgroundColor = builder.mLabelBackgroundColor;
        mLabelClickable = builder.mLabelClickable;
        mFabSize = builder.mFabSize;
        mTheme = builder.mTheme;
    }

    public int getId() {
        return mId;
    }

    public String getLabel(Context context) {
        if (mLabel != null) {
            return mLabel;
        } else if (mLabelRes != RESOURCE_NOT_SET) {
            return context.getString(mLabelRes);
        } else {
            return null;
        }
    }

    public String getContentDescription(Context context) {
        if (mContentDescription != null) {
            return mContentDescription;
        } else if (mContentDescriptionRes != RESOURCE_NOT_SET) {
            return context.getString(mContentDescriptionRes);
        } else {
            return null;
        }
    }

    /**
     * Gets the current Drawable, or null if no Drawable has been assigned.
     *
     * @param context A context to retrieve the Drawable from (needed for SpeedDialActionItem.Builder(int, int).
     * @return the speed dial item drawable, or null if no drawable has been assigned.
     */
    public Element getFabImageDrawable(Context context) {
        if (mFabImageDrawable != null) {
            return mFabImageDrawable;
        } else if (mFabImageResource != RESOURCE_NOT_SET) {
            return new VectorElement(context, mFabImageResource);
        } else {
            return null;
        }
    }

    public int getFabImageTintColor() {
        return mFabImageTintColor;
    }

    public boolean getFabImageTint() {
        return mFabImageTint;
    }

    @FabType
    public String getFabType() {
        return mFabType;
    }

    public int getFabBackgroundColor() {
        return mFabBackgroundColor;
    }

    public int getLabelColor() {
        return mLabelColor;
    }

    public int getLabelBackgroundColor() {
        return mLabelBackgroundColor;
    }

    public boolean isLabelClickable() {
        return mLabelClickable;
    }

    public FabWithLabelView createFabWithLabelView(Context context) {
        FabWithLabelView fabWithLabelView = new FabWithLabelView(context);
        fabWithLabelView.setSpeedDialActionItem(this);
        return fabWithLabelView;
    }

    public int getFabSize() {
        return mFabSize;
    }

    public static class Builder {
        private final int mId;
        private final int mFabImageResource;
        private final Element mFabImageDrawable;
        private int mFabImageTintColor = RESOURCE_NOT_SET;
        private boolean mFabImageTint = true;

        private String mFabType = TYPE_NORMAL;
        private String mLabel;
        private int mLabelRes = RESOURCE_NOT_SET;
        private String mContentDescription;
        private int mContentDescriptionRes = RESOURCE_NOT_SET;
        private int mFabBackgroundColor = RESOURCE_NOT_SET;
        private int mLabelColor = RESOURCE_NOT_SET;
        private int mLabelBackgroundColor = RESOURCE_NOT_SET;
        private boolean mLabelClickable = true;
        private int mFabSize = FloatingActionButton.SIZE_MINI;
        private int mTheme = RESOURCE_NOT_SET;

        /**
         * Creates a builder for a speed dial action item that uses a media as icon.
         *
         * @param id               the identifier for this action item. The identifier must be unique to the instance
         *                         of {@link SpeedDialView}. The identifier should be a positive number.
         * @param fabImageResource resId the resource identifier of the drawable
         */
        public Builder(int id, int fabImageResource) {
            mId = id;
            mFabImageResource = fabImageResource;
            mFabImageDrawable = null;
        }

        /**
         * Creates a builder for a speed dial action item that uses a {@link Element} as icon.
         * <p class="note">{@link Element} are not parcelables so is not possible to restore them when the view is
         * recreated for example after an orientation change. If possible always use the {@link #Builder(int, int)}</p>
         *
         * @param id       the identifier for this action item. The identifier must be unique to the instance
         *                 of {@link SpeedDialView}. The identifier should be a positive number.
         * @param drawable the Drawable to set, or null to clear the content
         */
        public Builder(int id, Element drawable) {
            mId = id;
            mFabImageDrawable = drawable;
            mFabImageResource = RESOURCE_NOT_SET;
        }

        /**
         * Creates a builder for a speed dial action item that uses a {@link SpeedDialActionItem} instance to
         * initialize the default values.
         *
         * @param speedDialActionItem it will be used for the default values of the builder.
         */
        public Builder(SpeedDialActionItem speedDialActionItem) {
            mId = speedDialActionItem.mId;
            mLabel = speedDialActionItem.mLabel;
            mLabelRes = speedDialActionItem.mLabelRes;
            mContentDescription = speedDialActionItem.mContentDescription;
            mContentDescriptionRes = speedDialActionItem.mContentDescriptionRes;
            mFabImageResource = speedDialActionItem.mFabImageResource;
            mFabImageDrawable = speedDialActionItem.mFabImageDrawable;
            mFabImageTintColor = speedDialActionItem.mFabImageTintColor;
            mFabImageTint = speedDialActionItem.mFabImageTint;
            mFabType = speedDialActionItem.mFabType;
            mFabBackgroundColor = speedDialActionItem.mFabBackgroundColor;
            mLabelColor = speedDialActionItem.mLabelColor;
            mLabelBackgroundColor = speedDialActionItem.mLabelBackgroundColor;
            mLabelClickable = speedDialActionItem.mLabelClickable;
            mFabSize = speedDialActionItem.mFabSize;
            mTheme = speedDialActionItem.mTheme;
        }

        public Builder setLabel(String label) {
            mLabel = label;
            if (mContentDescription == null || mContentDescriptionRes == RESOURCE_NOT_SET) {
                mContentDescription = label;
            }
            return this;
        }

        public Builder setLabel(int labelRes) {
            mLabelRes = labelRes;
            if (mContentDescription == null || mContentDescriptionRes == RESOURCE_NOT_SET) {
                mContentDescriptionRes = labelRes;
            }
            return this;
        }

        public Builder setContentDescription(String contentDescription) {
            mContentDescription = contentDescription;
            return this;
        }

        public Builder setContentDescription(int contentDescriptionRes) {
            mContentDescriptionRes = contentDescriptionRes;
            return this;
        }

        public Builder setFabImageTintColor(Integer fabImageTintColor) {
            if (fabImageTintColor == null) {
                mFabImageTint = false;
            } else {
                mFabImageTint = true;
                mFabImageTintColor = fabImageTintColor;
            }
            return this;
        }

        /**
         * set SpeedDialActionItem size.
         * SpeedDialActionItem.TYPE_NORMAL Use normal Fab.
         * SpeedDialActionItem.TYPE_FILL Set Floating Action Button image to fill the button.
         */
        public Builder setFabType(@FabType String fabType) {
            mFabType = fabType;
            return this;
        }

        public Builder setFabBackgroundColor(int fabBackgroundColor) {
            mFabBackgroundColor = fabBackgroundColor;
            return this;
        }

        public Builder setLabelColor(int labelColor) {
            mLabelColor = labelColor;
            return this;
        }

        public Builder setLabelBackgroundColor(int labelBackgroundColor) {
            mLabelBackgroundColor = labelBackgroundColor;
            return this;
        }

        public Builder setLabelClickable(boolean labelClickable) {
            mLabelClickable = labelClickable;
            return this;
        }

        public Builder setTheme(int mTheme) {
            this.mTheme = mTheme;
            return this;
        }

        public SpeedDialActionItem create() {
            return new SpeedDialActionItem(this);
        }

        public Builder setFabSize(int fabSize) {
            mFabSize = fabSize;
            return this;
        }

    }

    @Override
    public boolean marshalling(Parcel dest) {
        dest.writeInt(this.mId);
        dest.writeString(this.mLabel);
        dest.writeInt(this.mLabelRes);
        dest.writeString(this.mContentDescription);
        dest.writeInt(this.mContentDescriptionRes);
        dest.writeInt(this.mFabImageResource);
        dest.writeInt(this.mFabImageTintColor);
        dest.writeByte(this.mFabImageTint ? (byte) 1 : (byte) 0);
        dest.writeString(this.mFabType);
        dest.writeInt(this.mFabBackgroundColor);
        dest.writeInt(this.mLabelColor);
        dest.writeInt(this.mLabelBackgroundColor);
        dest.writeByte(this.mLabelClickable ? (byte) 1 : (byte) 0);
        dest.writeInt(this.mFabSize);
        dest.writeInt(this.mTheme);
        return true;
    }

    @Override
    public boolean unmarshalling(Parcel in) {
        this.mId = in.readInt();
        this.mLabel = in.readString();
        this.mLabelRes = in.readInt();
        this.mContentDescription = in.readString();
        this.mContentDescriptionRes = in.readInt();
        this.mFabImageResource = in.readInt();
        this.mFabImageDrawable = null;
        this.mFabImageTintColor = in.readInt();
        this.mFabImageTint = in.readByte() != 0;
        this.mFabType = in.readString();
        this.mFabBackgroundColor = in.readInt();
        this.mLabelColor = in.readInt();
        this.mLabelBackgroundColor = in.readInt();
        this.mLabelClickable = in.readByte() != 0;
        this.mFabSize = in.readInt();
        this.mTheme = in.readInt();
        return true;
    }

    @Override
    public boolean hasFileDescriptor() {
        return false;
    }

    public static final Sequenceable.Producer PRODUCER = in -> {
        SpeedDialActionItem instance = new SpeedDialActionItem();
        instance.unmarshalling(in);
        return instance;
    };

}
